﻿using System.Collections.Generic;
using System.Html;

namespace Db7
{
    public class VTable : VirtualElement
    {
        public VTable()
        {
            Tag = "table";
            Init = delegate()
            {
                DefaultPreRender();
            };
        }

        public void DefaultInit()
        {
            //TODO:  Sort Columns
        }

        private VirtualElement GenerateBodyRow(int ithRow, Element tr)
        {
            VirtualElement tBodyRow = new VirtualElement(); tBodyRow.Tag = "tr";
            //Util.Debug();
            string idx = ithRow.ToString();
            tBodyRow.AttributesNN.SetKey("_idx", idx);
            if (tr != null)
            {
                Util.SetAttribute(tr, "_idx", idx);
            }
            foreach (Column col in this.Columns)
            {
                VirtualElement td = new VirtualElement(); tBodyRow.ChildrenNN.Add(td);
                td.Tag = "td"; td.Text = col.RowIndexToBodyCellContent(ithRow);
            }
            if (tr != null)
            {
                RenderContext.RenderInsideElement(tr, tBodyRow);
            }
            return tBodyRow;
        }

        public void DefaultPreRender()
        {
            //TODO:  any type of cleanup?
            Children = new List<VirtualElement>();
            VirtualElement tHead = new VirtualElement(); Children.Add(tHead);
            tHead.Tag = "thead";
            VirtualElement tRow = new VirtualElement(); tHead.ChildrenNN.Add(tRow);
            tRow.Tag = "tr";
            foreach (Column col in this.Columns)
            {
                VirtualElement th = new VirtualElement(); tRow.ChildrenNN.Add(th);
                th.Tag = "th"; th.Text = col.HeaderText;
            }
            VirtualElement tBody = new VirtualElement(); Children.Add(tBody); tBody.Tag = "tbody";
            int ubound = PageSize_D == Util.NaN ? NumberOfRows_D : PageSize_D;
            for (int i = 0; i < ubound; i++)
            {
                VirtualElement tBodyRow = GenerateBodyRow(i, null);
               
                tBody.ChildrenNN.Add(tBodyRow);
                //Util.Debug();
                //tBodyRow.AttributesNN.SetKey("_idx", i.ToString());
                //foreach (Column col in this.Columns)
                //{
                //    VirtualElement td = new VirtualElement(); tBodyRow.ChildrenNN.Add(td);
                //    td.Tag = "td"; td.Text = col.RowIndexToBodyCellContent(i);
                //}
            }
            StartingRow_DB.AddOnUpdateNotification(OnStartingRowChange);
        }

        private int _PreviousStartRow;

        private void OnStartingRowChange()
        {
            //Util.Debug();
            TableElement table = PhysicalElement.As<TableElement>();
            TableSectionElement tse = table.tBodies[0].As<TableSectionElement>();
            int firstRow = -1;
            TableRowElement firstRowElement = null;
            //TableRowElement lastRowElement = null;
            int lastRow = StartingRow_D - 1;
            for (int i = tse.Rows.Length - 1; i > -1; i--)
            {
                #region remove non relevant rows
                TableRowElement tr = tse.Rows[i].As<TableRowElement>();
                string _idx = Util.GetAttribute(tr, "_idx") as string;
                int idx = int.Parse(_idx);
                Util.Log("idx = " + idx);
                if ( (idx < StartingRow_D) || (idx > StartingRow_D + PageSize_D))
                {
                    tse.RemoveChild(tr);
                }
                else
                {
                    if (lastRow == StartingRow_D - 1)
                    {
                        lastRow = idx;
                        Util.Log("lastRow = " + idx);
                    }
                    firstRow = idx;
                    firstRowElement = tr;
                }
                #endregion
                

            }
            //Element tempParent = Document.CreateElement("tbody");
            #region Add top rows
            //Util.Debug();
            //if (firstRow > 0)
            {
                Util.Log("AddTopRows from " + (firstRow - 1) + " down to " + StartingRow_D);
                Element topRow = firstRowElement;
                for (int i = firstRow - 1; i >= StartingRow_D; i--)
                {
                    Element treNew = Document.CreateElement("tr");
                    this.GenerateBodyRow(i, treNew);
                    topRow = tse.InsertBefore(treNew, topRow);

                }
            }
            #endregion
            #region Add Bottom Rows
            
            for (int i = lastRow + 1; i < StartingRow_D + PageSize_D ; i++)
            {
                Element treNew = Document.CreateElement("tr");
                
                //string trTest = "<td>test " + i + "</td>";
                this.GenerateBodyRow(i, treNew);
                
                //treNew.RenderInsideElement(tempParent);
                tse.AppendChild(treNew);
                //tse.InsertBefore(treNew, firstRowElement);
            }
            #endregion
            //if (StartingRow_D > _PreviousStartRow)
            //{
            //    for (int i = StartingRow_D - _PreviousStartRow - 1; i >= _PreviousStartRow; i--)
            //    {
            //        TableRowElement tr = tse.Rows[i].As<TableRowElement>();
            //        if (tr == null) continue;
            //        tse.RemoveChild(tr);
            //    }
            //}
            _PreviousStartRow = StartingRow_D;
        }

        #region public properties

        public List<Column> Columns = new List<Column>();

        public IntBinder NumberOfRows_DB;

        public int NumberOfRows_D
        {
            get
            {
                return IntBinder.Get(NumberOfRows_DB);
            }
            set
            {
                NumberOfRows_DB = IntBinder.Set(NumberOfRows_DB, value);
            }
        }

        public IntBinder PageSize_DB;

        public int PageSize_D
        {
            get { return IntBinder.Get(PageSize_DB); }
            set { PageSize_DB = IntBinder.Set(PageSize_DB, value); }
        }


        public IntBinder StartingRow_DB;
        public int StartingRow_D
        {
            get
            {
                return IntBinder.Get(StartingRow_DB);
            }
            set
            {
                StartingRow_DB = IntBinder.Set(StartingRow_DB, value);
            }
        }
        #endregion

    }
}
